/**
 * dxFacial - JavaScript wrapper for the native facial recognition module.
 *
 * This module provides a singleton-like interface to the underlying C++ facial
 * recognition functionality. It is designed to be consistent with the style of
 * other native module wrappers like dxNetwork.
 *
 * Features:
 * - Initialize/deinitialize the face engine and cameras.
 * - Retrieve recognition events and high-frequency detection data separately.
 * - Configure operational modes (e.g., liveness, recognition, compare).
 * - Manage the face feature database (register, delete, query).
 * - Control the engine's runtime state (pause/resume) and get status info.
 *
 * Usage:
 * - Call `init()` once with a configuration object.
 * - Periodically call `getRecognitionEvent()` to process important results.
 * - Periodically call `getDetectionData()` in your UI loop to draw tracking boxes.
 * - Use other methods like `registerFeature`, `setMode`, etc., as needed.
 */
import { Facial } from './libvbar-m-dxfacial.so'; // Placeholder for native module import
import logger from './dxLogger.js';

const dxFacial = {};

// --- Constants & Enums ---


// Instantiate the native object immediately.
// Thanks to ES module caching, this will only run once.
const _native = new Facial();
let _callbacks = {};


// --- Public API ---

/**
 * Initializes the facial recognition module. Must be called before any other function.
 * @param {object} [config={}] - Configuration object.
 * @param {object} [config.rgb] - Configuration for the RGB camera.
 * @param {object} [config.nir] - Configuration for the NIR (infrared) camera.
 * @param {number} [config.db_max] - Max number of faces in the database.
 * @param {string} [config.db_path] - Path to the face database file.
 * @param {string} [config.det_max] - Maximum number of faces to detect.
 * @param {string} [config.det_min_distance_cm] - Minimum distance in centimeters for detection.
 * @param {string} [config.det_max_distance_cm] - Maximum distance in centimeters for detection.
 * @param {string} [config.det_timeout_ms] - Timeout in milliseconds for detection.
 * @param {string} [config.liv_enable] - Live detection switch
 * @param {string} [config.liv_threshold] - Threshold for living score.
 * @param {string} [config.com_enable] - Face comparison switch
 * @param {string} [config.com_threshold] - Threshold for compare score.
 * @param {string} [config.rec_timeout_ms] - Timeout in milliseconds for recognition.
 * @param {string} [config.x_map] - X axis coordinate mapping parameters.
 * @param {string} [config.y_map] - Y axis coordinate mapping parameters.
 * @param {number} [config.pose_score_threshold] - Pose score threshold.
 */
dxFacial.init = function (config = {}) {
    _native.init(config); // Throws on error
    logger.info("DxFacial initialized successfully.");
};

/**
 * Deinitializes the module, releasing all resources.
 */
dxFacial.deinit = function () {
    _native.deinit();
    logger.info("DxFacial deinitialized.");
};

/**
 * Sets callback handlers for facial recognition events.
 * @param {object} callbacks - An object containing callback functions.
 * @param {function(event:object)} [callbacks.onRecognition] - Called when a recognition event occurs.
 * The event object contains details like `userId`, `feature`, `isRecognition`, etc.
 */
dxFacial.setCallbacks = function (callbacks) {
    _callbacks = callbacks || {};
};


/**
 * Processes the recognition event queue. Should be called periodically in a loop (e.g., setInterval).
 * If a recognition event is available, the `onRecognition` callback will be triggered.
 * @example
 * dxFacial.setCallbacks({
 *   onRecognition: (event) => {
 *     logger.info('Recognition Event:', event);
 *     event.id  // face id
 *     event.rect  // face bounding box coordinates
 *     event.is_rec  // whether to recognize
 *     event.picPath  // face picture path
 *     event.isCompare  // whether to compare
 *     event.compareScore  // compare score
 *     event.userId  // user id
 *     event.feature  // face feature
 *   }
 * });
 * setInterval(() => dxFacial.loop(), 50);
 */
dxFacial.loop = function () {
    const event = _native.getRecognitionEvent();
    if (event && typeof _callbacks.onRecognition === 'function') {
        _callbacks.onRecognition(event);
    }
};

/**
 * Retrieves the latest face detection data for UI purposes (e.g., drawing bounding boxes).
 * @return {array} [data] - Array of detected face objects.
 * @return {number} [data.id] - Face id.
 * @return {number} [data.status] - Face status. 0：detect pass、1：live pass、2：compare pass、3：compare fail
 * @return {array} [data.rect] - Face bounding box coordinates.
 * @return {number} [data.qualityScore] - Face quality score.
 * @return {number} [data.livingScore] - Face living score.
 */
dxFacial.getDetectionData = function () {
    return _native.getDetectionData();
};

/**
 * Sets the engine status (running or paused).
 * @param {boolean} isRunning - `true` to run, `false` to pause.
 */
dxFacial.setStatus = function (isRunning) {
    _native.setStatus(isRunning);
};

/**
 * Gets the estimated environment brightness.
 * @returns {number} Brightness level.
 */
dxFacial.getEnvBrightness = function () {
    return _native.getEnvBrightness();
};

/**
 * Gets the number of people detected by the NIR camera.
 * @returns {number} Number of people detected.
 */
dxFacial.getNirPersonCount = function () {
    return _native.getNirPersonCount();
};

/**
 * Gets the current engine configuration.
 * @returns {object} Configuration parameters.
 * @return {number} [config.db_max] - Max number of faces in the database.
 * @return {string} [config.db_path] - Path to the face database file.
 * @return {string} [config.det_max] - Maximum number of faces to detect.
 * @return {string} [config.det_min_distance_cm] - Minimum distance in centimeters for detection.
 * @return {string} [config.det_max_distance_cm] - Maximum distance in centimeters for detection.
 * @return {string} [config.det_timeout_ms] - Timeout in milliseconds for detection.
 * @return {string} [config.liv_enable] - Live detection switch
 * @return {string} [config.liv_threshold] - Threshold for living score.
 * @return {string} [config.com_enable] - Face comparison switch
 * @return {string} [config.com_threshold] - Threshold for compare score.
 * @return {string} [config.rec_timeout_ms] - Timeout in milliseconds for recognition.
 * @return {string} [config.x_map] - X axis coordinate mapping parameters.
 * @return {string} [config.y_map] - Y axis coordinate mapping parameters.
 */
dxFacial.getConfig = function () {
    return _native.getConfig();
};

/**
 * Sets or updates the engine configuration.
 * @param {object} [config={}] - Configuration object.
 * @param {number} [config.db_max] - Max number of faces in the database.
 * @param {string} [config.db_path] - Path to the face database file.
 * @param {string} [config.det_max] - Maximum number of faces to detect.
 * @param {string} [config.det_min_distance_cm] - Minimum distance in centimeters for detection.
 * @param {string} [config.det_max_distance_cm] - Maximum distance in centimeters for detection.
 * @param {string} [config.det_timeout_ms] - Timeout in milliseconds for detection.
 * @param {string} [config.liv_enable] - Live detection switch
 * @param {string} [config.liv_threshold] - Threshold for living score.
 * @param {string} [config.com_enable] - Face comparison switch
 * @param {string} [config.com_threshold] - Threshold for compare score.
 * @param {string} [config.rec_timeout_ms] - Timeout in milliseconds for recognition.
 * @param {string} [config.x_map] - X axis coordinate mapping parameters.
 * @param {string} [config.y_map] - Y axis coordinate mapping parameters.
 * @param {number} [config.pose_score_threshold] - Pose score threshold.
 */
dxFacial.setConfig = function (config) {
    _native.setConfig(config);
};

/**
 * Obtain the facial feature values of the camera
 * @param {number} timeout - The timeout in milliseconds.
 * @return {object} - Configuration object.
 * @return {number} - qualityScore.
 * @return {string} - picPath.
 * @return {object} - rect: {x, y, w, h}.
 * @return {string} - feature.
 */
dxFacial.getFeaByCap = function (timeout) {
    return _native.getFeaByCap(timeout);
};

/**
 * Obtain the facial feature values of the file
 * @param {number} timeout - The timeout in milliseconds.
 * @param {string} filePath - The file path.
 * @returns {object} - The result object.
 * @returns {number} - qualityScore.
 * @returns {object} - rect: {x, y, w, h}.
 * @returns {string} - feature.
 */
dxFacial.getFeaByFile = function (filePath) {
    return _native.getFeaByFile(filePath);
};

/**
 * compare a face feature with the database.
 * @param {string} featureBase64 - The base64-encoded feature string.
 * @returns {object} - The result object.
 * @return {number} score.
 * @return {string} userId.
 */
dxFacial.compareFea = function (featureBase64) {
    return _native.compareFea(featureBase64);
};

/**
 * add a face feature into the database.
 * @param {string} userId - The user ID to associate with the feature.
 * @param {string} featureBase64 - The base64-encoded feature string.
 * @returns {number} Result code.
 */
dxFacial.addFea = function (userId, featureBase64) {
    return _native.addFea(userId, featureBase64);
};

/**
 * updata a face feature into the database.
 * @param {string} userId - The user ID to associate with the feature.
 * @param {string} featureBase64 - The base64-encoded feature string.
 * @returns {number} Result code.
 */
dxFacial.updateFea = function (userId, featureBase64) {
    return _native.updateFea(userId, featureBase64);
};

/**
 * Deletes a user from the feature database.
 * @param {string} userId - The user ID to delete.
 * @returns {number} Result code.
 */
dxFacial.deleteFea = function (userId) {
    return _native.deleteFea(userId);
};

/**
 * Clears all features from the database.
 * @returns {number} Result code.
 */
dxFacial.cleanFea = function () {
    return _native.cleanFea();
};


/**
 * Gets the native module instance.
 * @returns {object|null}
 */
dxFacial.getNative = function () {
    return _native;
};

export default dxFacial; 